<template>
  <div>
    <!-- 由于上传地址使用的是element上传示例的地址，如报错或失效请更换。-->
    <a-upload
    accept=".xlsx"
    action='https://jsonplaceholder.typicode.com/posts/'
    :file-list="fileListcl"
    :remove="handleRemove"
    @change="upload">
      <a-button type="danger">上传文件(*.xlsx)</a-button>
    </a-upload>
    <!-- END -->

    <!-- 预览表格 -->
    <a-table
    :columns="columns"
    :data-source="tableData"
    :scroll="{ x: 1500, y: 350 }"
    :rowKey="(record,index) => {return index}"
    />
    <!-- END -->
  </div>
</template>

<script>
export default {
  data() {
    return {

      // 已上传的文件列表
      fileListcl: [],

      // 表格相关
      columns: [],//表格列
      tableData: [],//表格内容
    }
  },

  methods: {

        /**
         * 文件上传(Chang事件)
         * @description [此回调会运行三次 上传中、完成、失败都会调用这个函数]
         * @description 首先判断是否成功上传，如成功上传则调用构建表格函数
         * @param {Object} info - 回调信息
         * @return void
         */
        upload(info) {
          // 判断文件类型是否是EXCEL(不是的话直接跳过)
          if(info.fileList[0].type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'){
              
              // 赋值已上传文件列表
              let fileList = [...info.fileList];
              this.fileListcl = fileList.slice(-1);

              // [状态] 文件上传中
              if (info.file.status === 'uploading') { }

              // [状态] 文件上传成功
              if (info.file.status === 'done') {
                  // 构造表格数据(从表格中取出数据赋值到表格组件)
                  this.importfile(info.file)
              }
          }
        },

        /**
         * 构建表格数据
         * @description 获取上传excel数据并赋值给表格数据
         * @param {obj} - EXCEL文件信息
         * @return void
         */
        importfile(obj) {
          const _this = this
          const reader = new FileReader()

          _this.tableData = []
          _this.columns = []

          reader.readAsArrayBuffer(obj.originFileObj)//需要传blob类型
          reader.onload = function () {
            const buffer = reader.result
            const bytes = new Uint8Array(buffer)
            const length = bytes.byteLength

            let binary = ''
            for (let i = 0; i < length; i++) {
              binary += String.fromCharCode(bytes[i])
            }

            //引用刚才npm安装的
            const XLSX = require('xlsx')
            const wb = XLSX.read(binary, {//binary
                type: 'binary',
            })

            // api配置官方文档：https://github.com/rockboom/SheetJS-docs-zh-CN#json
            const sheet2JSONOpts = {
                raw: false,//使用原生值 (true) 或者格式化为字符串(false) | 解析单元格(解析成字符串就是false)
                /** Default value for null/undefined values */
                defval: '-',//给defval赋值为空的字符串
                range: 1,//不解析第一行(标题行)
            }
            
            // sheet_to_json 解析Excel文件
            const outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], sheet2JSONOpts)
            console.log(outdata) //此为取到的excel中全部内容，你可以进行改数据或直接搞页面！

            // 给Ant表格组件提供数据(包括列与内容)
            // 用解析出来的数据,进行清洗、添加,让其表格组件显示数据。
            let tableheader = outdata[0]
            for(let val in tableheader){
              _this.columns.push({//column表格列配置
                  title: val,
                  dataIndex: val,
                  key: val,
                  align: 'center',
                  ellipsis: true,
                  width: '150px'
              })
            }
            outdata.forEach((v,i)=>{//内容配置(利用key来当表格索引)
                // console.log(v,i)
                v={...v, "key":i}
            })

            // 复制最终数据
            _this.tableData = outdata
          }
      },

      /**
       * 用户点击移除已上传文件
       * @description 移除后需要清空已上传文件列表
       * @param {Array} file - 当前文件信息
       * @return void
       */
      handleRemove(file) {
          try {
              // 清空已上传文件列表
              this.fileListcl = []

              // 清空当前表格数据
              this.tableData = []
              this.columns = []
              // 提示信息
              this.$message.success('文件成功移除')
          } catch (error) {}
      },
      
  }
}
</script>

<style>

</style>